Exposing Process State to HyperBEAM
HyperBEAM introduces a powerful feature for exposing parts of a process's state for immediate reading over HTTP. This improves performance for web frontends and data services by replacing the need for dryrun
calls, which were a known bottleneck on legacynet
.
The Patch Device
The ~patch@1.0
device is the mechanism that allows AO processes to make parts of their internal state readable via direct HTTP GET requests.
How it Works
Exposing state is a four-step process involving your process and HyperBEAM:
- Process Logic: From your process (e.g., in Lua or WASM), send an outbound message to the
~patch@1.0
device. - Patch Message Format: The message must include
device
andcache
tags.luaSend({ Target = ao.id, device = 'patch@1.0', cache = { mydatakey = MyValue } })
- HyperBEAM Execution: HyperBEAM's
dev_patch
module processes this message, mapping the key-value pairs from thecache
table to a URL path. - HTTP Access: The exposed data is then immediately available via a standard HTTP GET request to the process's endpoint.HyperBEAM
GET /<process-id>~process@1.0/compute/cache/<mydatakey>
Initial State Sync (Optional)
To make data available immediately on process creation, you can patch its initial state. A common pattern is to use a flag to ensure this sync only runs once, as shown in this example for a token's Balances
and TotalSupply
.
-- Place this logic at the top level of your process script,
-- outside of specific handlers, so it runs on load.
Balances = { token1 = 100, token2 = 200 } -- A table of balances
TotalSupply = 1984 -- A single total supply value
-- 1. Initialize Flag:
-- Initializes a flag if it doesn't exist.
InitialSync = InitialSync or 'INCOMPLETE'
-- 2. Check Flag:
-- Checks if the sync has already run.
if InitialSync == 'INCOMPLETE' then
-- 3. Patch State:
-- The `Send` call patches the state, making it available at endpoints like:
-- /cache/balances
-- /cache/totalsupply
Send({ device = 'patch@1.0', cache = { balances = Balances, totalsupply = TotalSupply } })
-- 4. Update Flag:
-- Updates the flag to prevent the sync from running again.
InitialSync = 'COMPLETE'
print("Initial state sync complete. Balances and TotalSupply patched.")
end
This pattern makes essential data queryable upon process creation, boosting application responsiveness.
Example (Lua in aos
)
This handler exposes a currentstatus
key that can be read via HTTP after the PublishData
action is called.
-- In your process code (e.g., loaded via .load)
Handlers.add(
"PublishData",
Handlers.utils.hasMatchingTag("Action", "PublishData"),
function (msg)
local dataToPublish = "Some important state: " .. math.random()
-- Expose 'currentstatus' key under the 'cache' path
Send({ device = 'patch@1.0', cache = { currentstatus = dataToPublish } })
print("Published data to /cache/currentstatus")
end
)
Avoiding Key Conflicts
Keys in the cache
table become URL path segments. To avoid conflicts with reserved HyperBEAM paths, use descriptive, specific keys. Avoid using reserved keywords such as:
now, compute, state, info, test
For instance, prefer a key like myappstate
over a generic key like state
.
WARNING
HTTP paths are case-insensitive. While the patch
device stores keys with case sensitivity (e.g., MyKey
vs mykey
), HTTP access to paths like the following is ambiguous and may lead to unpredictable results.
To prevent conflicts, always use lowercase keys in your cache
table (e.g., mykey
, usercount
).
GET /<process-id>~process@1.0/cache/mykey
Key Points
- Path Structure: Data is exposed at a path structured like this, where
<key>
is a key from yourcache
table:HyperBEAM/<process-id>~process@1.0/cache/<key>
- Data Types: Basic data types like strings and numbers work best. Complex objects may require serialization.
compute
vsnow
: Accessing patched data can be done via two main paths:HyperBEAMTheGET /<process-id>~process@1.0/compute/cache/... GET /<process-id>~process@1.0/now/cache/...
compute
endpoint serves the last known value quickly, whilenow
may perform additional computation to get the most recent state.- Read-Only Exposure: Patching is for efficient reads and does not replace your process's core state management logic.
Using the patch
device enables efficient, standard HTTP access to your process state, seamlessly connecting decentralized logic with web applications.
Next Steps
Now that you know how to expose static state, learn how to perform on-the-fly computations on that state by reading dynamic state.